package com.example.mybatis.controller;

import com.example.mybatis.enums.ConstantEnums;
import com.example.mybatis.form.UserForm;
import com.example.mybatis.model.CityTO;
import com.example.mybatis.model.User;
import com.example.mybatis.model.UserTO;
import com.example.mybatis.service.ICityService;
import com.example.mybatis.service.IRedisService;
import com.example.mybatis.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import com.example.mybatis.model.ServiceResponse;
import org.springframework.data.redis.core.ListOperations;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 利用redis缓存用户信息
 */

@RestController
@RequestMapping("/redis")
public class RedisController {
    public static final String REDIS_CACHE_PREFIX = "cache_prefix:";
    @Autowired
    private IRedisService redisService;

    @Autowired
    private IUserService userService;

    @Resource(name="objectRedisTemplate")
    private RedisTemplate<String,Object> redisTemplate;

    @Resource(name="listOpsTemplate")
    private RedisTemplate<String, CityTO> listOpsTemplate;


    @Autowired
    private ICityService cityService;

    @RequestMapping(value="/save",method= RequestMethod.POST)
    public ServiceResponse<String> saveUser(@RequestBody User user){
        ServiceResponse<String> response = new ServiceResponse<String>();
        redisService.saveUserInfo(user);
        response.setStatus(200);
        response.setMessage("ok");
        response.setData(user.getUuid());
        return response;
    }

    @RequestMapping(value="/get",method = RequestMethod.GET)
    public ServiceResponse<User> getUser(@RequestParam("uuid") String uuid){
        ServiceResponse<User> response = new ServiceResponse<>();
        User user = redisService.getUser(uuid);
        response.setStatus(200);
        response.setMessage("ok");
        response.setData(user);
        return response;
    }

    //一个简单的用户登录接口,用redis作缓存单个对象
    @RequestMapping(value="/login",method = RequestMethod.POST)
    public ServiceResponse<String> userLogin(UserForm userForm){
        ServiceResponse<String> response = new ServiceResponse<>();
        UserTO userTO = (UserTO) redisTemplate.opsForValue().get(REDIS_CACHE_PREFIX+userForm.getUserAccount());
        if(null==userTO){
            userTO = userService.queryUserInfoByAccount(userForm.getUserAccount()).getData();
            //缓存30分钟
            if(null==userTO || null!=userTO && !userTO.getPassword().equals(userForm.getPassword())){
                response.setStatus(ConstantEnums.LOGIN_ACCOUNT_PASSWORD_ERROR.getStatus());
                response.setMessage(ConstantEnums.LOGIN_ACCOUNT_PASSWORD_ERROR.getMessage());
                response.setData("login failed");
                return response;
            }
            redisTemplate.opsForValue().set(REDIS_CACHE_PREFIX+userForm.getUserAccount(),userTO,30, TimeUnit.MINUTES);
        }
        response.setStatus(ConstantEnums.LOGIN_SUCCESS.getStatus());
        response.setMessage(ConstantEnums.LOGIN_SUCCESS.getMessage());
        response.setData("ok");
        return response;
    }

    //退出登录
    @RequestMapping(value="/loginOut",method=RequestMethod.GET)
    public ServiceResponse<String> loginOut(@RequestParam("userAccount")String userAccount){
        ServiceResponse<String> response = new ServiceResponse<>();
        if(redisTemplate.opsForValue().get(REDIS_CACHE_PREFIX+userAccount)==null){
            response.setStatus(ConstantEnums.LOGIN_OFFLINE.getStatus());
            response.setMessage(ConstantEnums.LOGIN_OFFLINE.getMessage());
            return response;
        }
        Boolean result = redisTemplate.delete(REDIS_CACHE_PREFIX+userAccount);
        if(result){
            response.setStatus(ConstantEnums.LOGIN_OUT_SUCCESS.getStatus());
            response.setMessage(ConstantEnums.LOGIN_OUT_SUCCESS.getMessage());
            response.setData("index.html");
        }else{
            response.setStatus(ConstantEnums.LOGIN_OUT_ERROR.getStatus());
            response.setMessage(ConstantEnums.LOGIN_OUT_ERROR.getMessage());
        }
        return response;
    }

    //redisTemplate操作List数据结构
    @RequestMapping(value="/list/cities",method=RequestMethod.GET)
    public ServiceResponse<List<CityTO>> queryCitiesByParentCode(@RequestParam("parentCode") String parentCode){
        ServiceResponse<List<CityTO>> response = null;
        ListOperations<String, CityTO> listOps = listOpsTemplate.opsForList();
        List<CityTO> cityList = listOps.range(REDIS_CACHE_PREFIX+parentCode,0,-1);
        if(cityList.size()==0){
            response = cityService.queryCityByParentCode(parentCode);
            cityList = response.getData();
            CityTO[] tempArray = new CityTO[cityList.size()];
            CityTO[] cityArray = cityList.toArray(tempArray);
            if(cityList.size()>0){
                listOps.leftPushAll(REDIS_CACHE_PREFIX+parentCode,cityArray);
                //缓存12个小时
                listOpsTemplate.expire(REDIS_CACHE_PREFIX+parentCode,12,TimeUnit.HOURS);
            }
        }else{
            response = new ServiceResponse();
            response.setStatus(200);
            response.setMessage("ok");
            response.setData(cityList);
        }

        return response;
    }

    @RequestMapping(value="/map/cities",method=RequestMethod.POST)
    public ServiceResponse<Map<String,List<CityTO>>> queryCitiesByParentCodes(@RequestBody List<String> parentCodes){
        ServiceResponse<Map<String,List<CityTO>>> response = new ServiceResponse<>();
        HashOperations<String,String,CityTO> hashOperations = listOpsTemplate.opsForHash();
        Map<String,List<CityTO>> resultMap = new HashMap<>();
        List<CityTO> cityList = null;
        for(String code:parentCodes){
            //先从redis缓存里面查
            cityList = hashOperations.values(REDIS_CACHE_PREFIX+"citiesMap:"+code);
            if(cityList.size()==0){
                //redis缓存里没有再去数据库查，并把查出来的对象放入redis的Map当中并设置缓存有效时间12h
                cityList = cityService.queryCityByParentCode(code).getData();
                for(CityTO cityTO:cityList){
                    hashOperations.put(REDIS_CACHE_PREFIX+"citiesMap:"+code,String.valueOf(cityTO.getCityCode()),cityTO);
                    listOpsTemplate.expire(String.valueOf(cityTO.getCityCode()),12,TimeUnit.HOURS);
                }
            }
            resultMap.put(String.valueOf(code),cityList);
        }
        response.setStatus(200);
        response.setMessage("ok");
        response.setData(resultMap);
        return response;
    }



}
